package com.example.onlinemonitoring.comCenter;

import com.example.onlinemonitoring.Util.CRC16;
import com.example.onlinemonitoring.Util.CommPortManager;
import com.example.onlinemonitoring.Util.HexUtil;
import com.example.onlinemonitoring.model.Appdevice;
import com.example.onlinemonitoring.model.Gispdhistory;
import com.example.onlinemonitoring.model.Gispdsensor;
import com.example.onlinemonitoring.model.Scpdhistory;
import com.example.onlinemonitoring.model.Scpdsensor;
import com.example.onlinemonitoring.model.Sctmnhistory;
import com.example.onlinemonitoring.model.Sctmnsensor;
import org.springframework.context.annotation.Scope;

import com.example.onlinemonitoring.serviceImpl.GispdsensorServiceImpl;
import com.example.onlinemonitoring.serviceImpl.ScpdsensorServiceImpl;
import com.example.onlinemonitoring.serviceImpl.SctmnsensorServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 开关柜测温和开关柜局放（济钢）
 */
@Service("sctmnCom")
@Scope("prototype")
public class SctmnCom extends CommPortManager {
    @Autowired
    private SctmnsensorServiceImpl sctmnserviceimpl;
    String recvmsg[] = new String[256];
    int cmdlen = 0;

    public void ClearCache() {
        for (int i = 0; i < recvmsg.length; i++) {
            recvmsg[i] = "";
        }
    }
    @Override
    public void receiveDatas(String str) {
        //setText(str+"receiveDatas");
        if (ad.getCommunicationmode() == 4) {
            // read61850(str);
        } else {
            switch (ad.getBrand()) {
                case "0":
                case "1":
                case "2":
                    Datajg(str);
                    break;
                case "3":
                    Databsq(str);
                    break;

                default:
                    return;
            }
        }
    }

    public void Datajg(String str) {
        setText(str);
        if (!str.substring(2, 4).equals("03") || currcmd >= recvmsg.length) {
            return;
        }
        String addrstr = str.substring(0, 2);
        Integer addrint = parsePHex4(addrstr);

        recvmsg[currcmd] = str.substring(6, str.length() - 4);
        boolean flag = false;
        for (int i = 0; i < cmdlen; i++) {
            if (recvmsg[i].isEmpty()) {
                flag = true;
            }
        }
        if (!flag) {
            reSend[addrint] = 0;
            String msg = "";
            String vmsg = "";
            if (ad.getBrand().equals("0")) {
                for (int i = 0; i < cmdlen; i++) {
                    msg += recvmsg[i];
                }
            } else {
                for (int i = 0; i < cmdlen / 2; i++) {
                    msg += recvmsg[i];
                }
                for (int i = cmdlen / 2; i < cmdlen; i++) {
                    vmsg += recvmsg[i];
                }
            }

            Sctmnsensor sctmn = new Sctmnsensor();
            sctmn.setStationid(ad.getStationid());
            sctmn.setDevicegroup(ad.getDevicegroup());
            sctmn.setDeviceaddr(addrint);
            List<Sctmnsensor> list = sctmnserviceimpl.getLists(sctmn);
            int index = 0, vindex = 0;
            for (Sctmnsensor ss : list) {
                sctmn.setPointaddr(ss.getPointaddr());
                try {
                    // 温度数据
                    sctmn.setLasta(parseHex4(msg.substring(index, index + 4)) * ss.getCof() + ss.getOffset());
                    index += 4;
                    sctmn.setLastb(parseHex4(msg.substring(index, index + 4)) * ss.getCof() + ss.getOffset());
                    index += 4;
                    sctmn.setLastc(parseHex4(msg.substring(index, index + 4)) * ss.getCof() + ss.getOffset());
                    index += 4;
                    if (ad.getBrand().equals("1")) {
                        // 电压数据
                        sctmn.setLastabv(parsePHex4(vmsg.substring(vindex, vindex + 4)) * 1f);
                        vindex += 4;
                        sctmn.setLastbbv(parsePHex4(vmsg.substring(vindex, vindex + 4)) * 1f);
                        vindex += 4;
                        sctmn.setLastcbv(parsePHex4(vmsg.substring(vindex, vindex + 4)) * 1f);
                        vindex += 4;
                    }
                } catch (Exception e) {
                    System.out.println(e.toString());
                    // TODO: handle exception
                }

                sctmn.setLastaalarmstatus(GetAlarmStatus(isnull(sctmn.getLasta()),
                        isnull(ss.getAalarmvalue()),
                        isnull(ss.getAalarmrelievevalue()),
                        isnull(ss.getAwarnvalue()),
                        isnull(ss.getAwarnrelievevalue()),
                        isnull(ss.getLastaalarmstatus()), true, ss.getPointname() + "A相温度", ss.getDevicegroup(),
                        ss.getDeviceaddr(), ss.getPointname(), ss.getPointaddr()));

                sctmn.setLastbalarmstatus(GetAlarmStatus(isnull(sctmn.getLastb()),
                        isnull(ss.getBalarmvalue()),
                        isnull(ss.getBalarmrelievevalue()),
                        isnull(ss.getBwarnvalue()),
                        isnull(ss.getBwarnrelievevalue()),
                        isnull(ss.getLastbalarmstatus()), true, ss.getPointname() + "B相温度", ss.getDevicegroup(),
                        ss.getDeviceaddr(), ss.getPointname(), ss.getPointaddr()));

                sctmn.setLastcalarmstatus(GetAlarmStatus(isnull(sctmn.getLastc()),
                        isnull(ss.getCalarmvalue()),
                        isnull(ss.getCalarmrelievevalue()),
                        isnull(ss.getCwarnvalue()),
                        isnull(ss.getCwarnrelievevalue()),
                        isnull(ss.getLastcalarmstatus()), true, ss.getPointname() + "C相温度", ss.getDevicegroup(),
                        ss.getDeviceaddr(), ss.getPointname(), ss.getPointaddr()));
                if (ad.getBrand().equals("1")) {
                    sctmn.setLastabvalarmstatus(GetAlarmStatus(isnull(sctmn.getLastabv()),
                            isnull(ss.getBvalarmvalue()),
                            isnull(ss.getBvalarmrelievevalue()),
                            isnull(ss.getBvwarnvalue()),
                            isnull(ss.getBvwarnrelievevalue()),
                            isnull(ss.getLastabvalarmstatus()), false, ss.getPointname() + "A相电池电压",
                            ss.getDevicegroup(),
                            ss.getDeviceaddr(), ss.getPointname(), ss.getPointaddr()));

                    sctmn.setLastbbvalarmstatus(GetAlarmStatus(isnull(sctmn.getLastbbv()),
                            isnull(ss.getBvalarmvalue()),
                            isnull(ss.getBvalarmrelievevalue()),
                            isnull(ss.getBvwarnvalue()),
                            isnull(ss.getBvwarnrelievevalue()),
                            isnull(ss.getLastbbvalarmstatus()), false, ss.getPointname() + "B相电池电压",
                            ss.getDevicegroup(),
                            ss.getDeviceaddr(), ss.getPointname(), ss.getPointaddr()));

                    sctmn.setLastcbvalarmstatus(GetAlarmStatus(isnull(sctmn.getLastcbv()),
                            isnull(ss.getBvalarmvalue()),
                            isnull(ss.getBvalarmrelievevalue()),
                            isnull(ss.getBvwarnvalue()),
                            isnull(ss.getBvwarnrelievevalue()),
                            isnull(ss.getLastcbvalarmstatus()), false, ss.getPointname() + "C相电池电压",
                            ss.getDevicegroup(),
                            ss.getDeviceaddr(), ss.getPointname(), ss.getPointaddr()));
                }
                String alarmMessage = "";
                alarmMessage += GetAlarmMessage(isnull(sctmn.getLastaalarmstatus()), ss.getPointname() + "A相温度");
                alarmMessage += GetAlarmMessage(isnull(sctmn.getLastbalarmstatus()), ss.getPointname() + "B相温度");
                alarmMessage += GetAlarmMessage(isnull(sctmn.getLastcalarmstatus()), ss.getPointname() + "C相温度");
                alarmMessage += GetAlarmMessage(isnull(sctmn.getLastabvalarmstatus()), ss.getPointname() + "A相电池电压");
                alarmMessage += GetAlarmMessage(isnull(sctmn.getLastbbvalarmstatus()), ss.getPointname() + "B相电池电压");
                alarmMessage += GetAlarmMessage(isnull(sctmn.getLastcbvalarmstatus()), ss.getPointname() + "C相电池电压");
                sctmn.setLastalarmlevel(HexUtil.MAX(new int[] {
                        isnull(sctmn.getLastaalarmstatus()),
                        isnull(sctmn.getLastbalarmstatus()),
                        isnull(sctmn.getLastcalarmstatus()),
                        isnull(sctmn.getLastabvalarmstatus()),
                        isnull(sctmn.getLastbbvalarmstatus()),
                        isnull(sctmn.getLastcbvalarmstatus()) }));

                sctmn.setLastalarmmessage(alarmMessage);
                sctmn.setLastcommunicationstatus(0);
                sctmn.setLastdatatime(new Date());
                sctmn.setLasthisdatatime(addHistory(ss));
                sctmnserviceimpl.Update(sctmn, false);
            }
            addrindex++;
            setText("开关柜测温数据解析完毕！");
        }
    }

    
    public void Databsq(String str) {
        setText(str);
        if (!str.substring(2, 4).equals("03") || currcmd >= recvmsg.length) {
            return;
        }
        String addrstr = str.substring(0, 2);
        Integer addrint = parsePHex4(addrstr);

        recvmsg[currcmd] = str.substring(6, str.length() - 4);
        boolean flag = false;
        for (int i = 0; i < cmdlen; i++) {
            if (recvmsg[i].isEmpty()) {
                flag = true;
            }
        }
        reSend[addrint] = 0;
        String msg = "";
        String vmsg = "";

        for (int i = 0; i < cmdlen; i++) {
            msg += recvmsg[i];
        }
        
        Sctmnsensor sctmn = new Sctmnsensor();
        sctmn.setStationid(ad.getStationid());
        sctmn.setDevicegroup(ad.getDevicegroup());
        sctmn.setDeviceaddr(addrint);
        Sctmnsensor ss = sctmnserviceimpl.getModel(sctmn);
        if (ss == null) {
            // setText("当前数据库无监测点：设备地址" + addr + "的监测点" + pointaddr + " ！ 请先添加该监测点！");
            return;
        }
        if (ss.getInuse() == 0)
            return;
        int index = 0;
        // 温度数据
        sctmn.setLasta(parseHex4(msg.substring(index, index + 4)) * ss.getCof() + ss.getOffset());
        
        sctmn.setLastaalarmstatus(GetAlarmStatus(isnull(sctmn.getLasta()),
        isnull(ss.getAalarmvalue()),
        isnull(ss.getAalarmrelievevalue()),
        isnull(ss.getAwarnvalue()),
        isnull(ss.getAwarnrelievevalue()),
        isnull(ss.getLastaalarmstatus()), true, ss.getPointname() + "温度", ss.getDevicegroup(),
        ss.getDeviceaddr(), ss.getPointname(), ss.getPointaddr()));
        String alarmMessage = "";
        alarmMessage += GetAlarmMessage(isnull(sctmn.getLastaalarmstatus()), ss.getPointname() + "温度");
        sctmn.setLastalarmmessage(alarmMessage);
        sctmn.setLastcommunicationstatus(0);
        sctmn.setLastdatatime(new Date());
        sctmn.setLasthisdatatime(addHistory(ss));
        sctmnserviceimpl.Update(sctmn, false);
        addrindex++;
        setText("开关柜测温数据解析完毕！");
    }
    private Date addHistory(Sctmnsensor sensor) {
        if (sensor != null) {
            if (sensor.getLasthisdatatime() == null) {
                add(sensor);
                return new Date();
            } else {
                long lasttime = 0;
                long nowtime = 0;
                try {
                    lasttime = HexUtil.todate(sensor.getLasthisdatatime()).getTime();
                    nowtime = HexUtil.todate(new Date()).getTime();
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                int timersp = 60000;
                if (sensor.getLastalarmlevel() != 0) {
                    timersp = ad.getHisalarmtimersp() * 1000;
                } else {
                    timersp = ad.getHistimersp() * 1000;
                }
                if (lasttime + timersp < nowtime) {
                    add(sensor);
                    return new Date();
                }
            }
        }
        return null;
    }

    private void add(Sctmnsensor sensor) {
        Sctmnhistory his = new Sctmnhistory();
        his.setStationid(sensor.getStationid());
        his.setDevicegroup(sensor.getDevicegroup());
        his.setDeviceaddr(sensor.getDeviceaddr());
        his.setPointaddr(sensor.getPointaddr());
        his.setAddrname(sensor.getAddrname());
        his.setPointname(sensor.getPointname());
        his.setDatatime(sensor.getLastdatatime());
        his.setA(sensor.getLasta());
        his.setB(sensor.getLastb());
        his.setC(sensor.getLastc());
        his.setAlarmlevel(sensor.getLastalarmlevel());
        his.setAlarmmessage(sensor.getLastalarmmessage());
        his.setAalarmstatus(sensor.getLastaalarmstatus());
        his.setBalarmstatus(sensor.getLastbalarmstatus());
        his.setCalarmstatus(sensor.getLastcalarmstatus());
        his.setMemo(sensor.getMemo());
        his.setInuse(sensor.getInuse());
        his.setStyle(sensor.getStyle());
        his.setAbv(sensor.getLastabv());
        his.setBbv(sensor.getLastbbv());
        his.setCbv(sensor.getLastcbv());
        his.setAbvalarmstatus(sensor.getLastabvalarmstatus());
        his.setBbvalarmstatus(sensor.getLastbbvalarmstatus());
        his.setCbvalarmstatus(sensor.getLastcbvalarmstatus());
        sctmnserviceimpl.Add(his);
    }

    @Async("threadPool")
    public void startSendThread(Appdevice Appdevice) throws Exception {
        String cmd[] = Appdevice.getCmd().split(",");
        cmdlen = cmd.length;
        checkType = "crc16";
        issend.put(Thread.currentThread().getId(), true);
        String cstr = "";
        int timeoutsp = (int) Math.round(Appdevice.getTimeoutsp() * 1000);
        timersp = (int) Math.round(Appdevice.getTimersp() * 1000);
        while (issend.get(Thread.currentThread().getId()) != null) {
            rlock.lock();
            try {
                if (isrun) {
                    if (addrindex > Appdevice.getAddrmax() || addrindex < Appdevice.getAddrmin())
                        addrindex = Appdevice.getAddrmin();
                    currcmd = 0;
                    for (int i = 0; i < cmd.length; i++) {
                        if (currcmd == 0) {
                            ClearCache();
                        }
                        cstr = String.format(cmd[currcmd], String.format("%02X", addrindex));
                        cstr = cstr + CRC16.calcCrc16(cstr);
                        Send(cstr);
                        sendCondition.await(timeoutsp, TimeUnit.MILLISECONDS);
                        currcmd++;
                    }

                    if (reSend[addrindex] > 3) {
                        sctmnserviceimpl.UpdateStatus(ad, addrindex, 1);
                        reSend[addrindex] = 0;
                        addrindex++;
                    }
                    reSend[addrindex]++;
                } else if (rescode != 0) {
                    setText(resmsg[rescode]);
                }
            } catch (Exception e) {
                // TODO: handle exception
            } finally {
                rlock.unlock();
            }
        }
    }
}
